package ewu

import ewu._

/**
 * KArray ist ein Array mit einem Indexbereich und einem Wertebereich.
 * Diese Werden ueber Index- bzw. ValueRanges definiert.
 * Wird keine ValueRange angegeben, umfasst der Wertebereich den der
 * scala.BigInt.
 * 
 * Arrayzugriffe für den Programmlauf werden in der Klasse
 * ArrayValue reguliert, da es sich bei diesen speziell um
 * Expressions handelt, mit denen die Whilesprache arbeitet.
 * 
 * Wird versucht, ein Wert ausserhalb des Indexbereichs zu erfragen,
 * wird eine IndexOutOfBoundsException geworfen.
 * Es ist moeglich eine Expression mit Environment zu uebergeben um
 * den Wert an der Stelle des Ergebnisses der Expression zu bekommen.
 * Ist die Expression nicht auswertbar, so wird eine
 * IllegalArgumentException geworfen
 * 
 * Eine Zuweisung an das KArray findet ueber die Indizes des
 * Indexbereiches statt.
 * Bsp:
 * val karray:KArray=new KArray(new IndexRange(5,10))
 * KArray.setValue(6,100)
 * 
 * Ergibt: [?,100,?,?,?,?]
 * 
 * Wird versucht einen Wert ausserhalb des Wertebereichs dem KArray
 * hinzuzufuegen, wird eine IllegalArgumentException geworfen.
 */

class KArray(index: IndexRange, value: ValueRange) {
  private val ifirst: Int = index.first
  private val ilast: Int = index.last
  private var array: Array[BigInt] = new Array[BigInt](0);

  if (!index.isEmpty) {
    array = new Array[BigInt](ilast - ifirst + 1)
  }

  def this(index: IndexRange) = this (index, null)

  def valueAt(i: Int): BigInt = {
    if(i == 1234567890)
      array(0)
    else
      array(i - ifirst)
  }

  def valueAt(posEx: Expression, env: Environment): BigInt = {
    posEx.evaluate(env) match {
      case Some(x) => valueAt(x.intValue)
      case _ => throw new IllegalArgumentException(
          "Expression not evaluable: " + posEx.toString)

    }
  }

  def setValue(posEx: Expression,
               env: Environment,
               newValue: BigInt) {
    posEx.evaluate(env) match {
      case Some(x) => setValue(x.intValue, newValue)
      case _ => throw new IllegalArgumentException(
          "Expression not evaluable: " + posEx.toString)
    }
  }

  def setValue(posIn: Int, newValue: BigInt) = {
    var pos: Int = posIn - ifirst
    if (value == null) {
      array(pos) = newValue
    }
    else {
      if (value.isInRange(newValue)) {
        array(pos) = newValue
      }
      else {
        throw new IllegalArgumentException("Value not in range")
      }
    }
  }

  override def toString: String = (index.toString + " => ["
    + array.mkString(",  ").replaceAll("null", "?") + "]")

  def first: BigInt = array(0)

  def last: BigInt = array(ilast - ifirst - 1)
}